package com.zmn.oms.business.impl.messageV1.common;

import com.alibaba.fastjson.JSON;
import com.zmn.base.engineer.common.dro.foreign.engineer.ForeignEngineerDetailInfoDRO;
import com.zmn.base.engineer.dubbo.interfaces.foreign.EngineerListRemoteService;
import com.zmn.base.shortlink.common.constant.DubboConsts;
import com.zmn.base.shortlink.common.dio.shortlink.ShortLinkDIO;
import com.zmn.base.shortlink.common.dro.shortlink.ShortLinkDRO;
import com.zmn.base.shortlink.common.enums.shortlink.ShortLinkTypeEnum;
import com.zmn.base.shortlink.dubbo.interfaces.shortlink.ShortLinkModifyRemoteService;
import com.zmn.common.constant.GlobalConsts;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.date.DateUtil;
import com.zmn.common.utils.number.NumberUtil;
import com.zmn.manager.redis.RedisManager;
import com.zmn.oms.business.interfaces.messageV1.common.MessageGetSendInfoService;
import com.zmn.oms.business.interfaces.warranty.OrderWarrantyBService;
import com.zmn.oms.common.constant.OrderStatusConsts;
import com.zmn.oms.common.constant.RedisKeyConsts;
import com.zmn.oms.model.dto.messageV1.ShortUrlDTO;
import com.zmn.oms.model.entity.orderappbind.OrderThirdAppBind;
import com.zmn.oms.model.entity.work.OrderWork;
import com.zmn.oms.model.vo.warranty.WarrantyVO;
import com.zmn.oms.services.interfaces.orderappbind.OrderThirdAppBindService;
import com.zmn.oms.services.interfaces.work.OrderWorkService;
import com.zmn.saas.common.dto.wechat.WeixinUserInfoDRO;
import com.zmn.saas.dubbo.dto.app.WxAppDRO;
import com.zmn.saas.dubbo.interfaces.app.AppRemoteService;
import com.zmn.saas.dubbo.interfaces.qrcode.PrivateQrCodeListRemoteService;
import com.zmn.uuc.common.dro.user.UserDetailDRO;
import com.zmn.uuc.common.dro.user.UserThirdBaseDRO;
import com.zmn.uuc.dubbo.interfaces.user.UserListRemoteService;
import com.zmn.uuc.dubbo.interfaces.user.UserThirdListRemoteService;
import groovy.util.logging.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
@Slf4j
public class MessageGetSendInfoServiceImpl implements MessageGetSendInfoService {
    private Logger logger = LoggerFactory.getLogger(MessageGetSendInfoServiceImpl.class);

    @Reference(version = DubboConsts.INTERFACE_VERSION, check = false)
    private ShortLinkModifyRemoteService shortLinkModifyRemoteService;
    @Reference(version = com.zmn.saas.dubbo.constant.SaasDubboConsts.INTERFACE_VERSION, check = false)
    private AppRemoteService appRemoteService;
    @Reference(version = com.zmn.uuc.common.constant.DubboConsts.INTERFACE_VERSION, check = false)
    private UserThirdListRemoteService userThirdListRemoteService;
    @Reference(version = com.zmn.uuc.common.constant.DubboConsts.INTERFACE_VERSION, check = false)
    private UserListRemoteService userListRemoteService;
    @Reference(version = com.zmn.base.engineer.common.constants.DubboConsts.INTERFACE_VERSION, check = false)
    private EngineerListRemoteService engineerListRemoteService;
    @Reference(version = com.zmn.saas.dubbo.constant.SaasDubboConsts.INTERFACE_VERSION, check = false)
    private PrivateQrCodeListRemoteService privateQrCodeListRemoteService;

    @Value("${spring.profiles.active}")
    private String active;
    @Autowired
    private RedisManager redisManager;
    @Autowired
    private OrderThirdAppBindService orderThirdAppBindService;
    @Autowired
    private OrderWorkService orderWorkService;
    @Autowired
    private OrderWarrantyBService orderWarrantyBService;


    @Override
    public boolean bindWechatAppToOrder(Long orderId, Long zmnUserId, Integer cityId, Integer plat) {
        OrderThirdAppBind orderThirdApp = orderThirdAppBindService.findByOrderIdAndPlatSrcMaster(orderId, plat);
        if (Objects.nonNull(orderThirdApp) && StringUtils.isNotBlank(orderThirdApp.getThirdAppId())) {
            return true;
        }
        ResponseDTO<WxAppDRO> resp = null;
        try {
            logger.info("订单号={},获取微信公众号getAppByPlatAndUserId信息入参plat={}，userId={}，cityId={}", orderId, plat, zmnUserId, cityId);
            resp = appRemoteService.getAppByPlatAndUserId(plat, zmnUserId, cityId);
            logger.info("订单号={},获取微信公众号getAppByPlatAndUserId信息出参:【{}】", orderId, JSON.toJSON(resp));
        } catch (Exception ex) {
            logger.error(String.format("订单号%s，获取微信公众号getAppByPlatAndUserId接口异常了:%s", orderId, ex.getMessage()), ex);
            return false;
        }
        WxAppDRO weChatApp = resp.getData();
        if (!resp.isSuccess() || Objects.isNull(weChatApp)) {
            logger.info("订单号{}send 获取公众号绑定接口失败  ============= ", orderId);
            return false;
        }

        // 全部失败
        if (StringUtils.isBlank(weChatApp.getThirdAppId())) {
            logger.info("订单号{}send 绑定公众号接口三方id为空，绑定失败 =============", orderId);
            return false;
        }

        // 处理绑定公众号渠道id
        Integer appChannelId = getWeChatChannelIdByThirdAppId(orderId, weChatApp.getThirdAppId());

        try {
            OrderThirdAppBind orderThirdAppBind = OrderThirdAppBind.builder()
                    .orderId(orderId)
                    .thirdAppId(weChatApp.getThirdAppId())
                    .thirdAppName(weChatApp.getName())
                    .appChannelId(Optional.ofNullable(appChannelId).orElse(0))
                    .appShopId(Optional.ofNullable(weChatApp.getShopId()).orElse(0))
                    .platWork(plat)
                    .appPlatId(100)
                    .type(10)
                    .creater("系统")
                    .build();
            logger.info("订单号{}send 开始绑定公众号信息json={}=============", orderId, JSON.toJSONString(orderThirdAppBind));
            int bind = orderThirdAppBindService.insertOrderThirdApp(orderThirdAppBind);
            logger.info("订单号{}send 绑定公众号结果{}=============", orderId, bind);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            return false;
        }
        return true;
    }

    @Override
    public boolean checkOrderBindAppOrBind(Long orderId, Integer plat) {
        // 公众号绑定失败后，师傅领单前，第二次进行绑定，进行容错处理
        OrderWork orderWork = orderWorkService.findOrderWorkByKey(orderId, orderId);
        if (Objects.isNull(orderWork)) {
            logger.info("订单号{}重试绑定未找到对应订单信息 ========>", orderId);
            return false;
        }
        // 订单状态小于分单，不容错处理
        if (orderWork.getStatus() < OrderStatusConsts.WORK_STATUS_ASSIGN) {
            logger.info("订单号{} 订单还未分单或撤回，不处理绑定信息，检测通过 =========== )", orderId);
            return true;
        }

        // 上门后不检测订单绑定状态
        if (orderWork.getStatus() > OrderStatusConsts.WORK_STATUS_TAKE) {
            logger.info("订单号{}订单状态大于接单状态，不处理绑定信息，检测通过  ========>", orderId);
            return true;
        }

        OrderThirdAppBind orderThirdAppBind = getOrderWeChatBindInfoForOrderBy(orderId, plat);
        if (Objects.nonNull(orderThirdAppBind)) {
            logger.info("订单号{}检测是否绑定公众号，订单已绑定公众号===检测通过 ========>", orderId);
            return true;
        }

        logger.info("订单号{}send 未检测到公众号绑定信息，再次发起公众号绑定请求 ==========>", orderId);
        boolean isBind = bindWechatAppToOrder(orderId, orderWork.getUserId(), orderWork.getCityId(), plat);
        if (!isBind) {
            logger.info("订单号{}send 再次绑定公众号失败，请联系saas人员排查原因。调用接口getAppByPlatAndUserId(plat={}, userId={}, cityId={})========>", orderId, plat, orderWork.getUserId(), orderWork.getCityId());
        }
        return isBind;
    }


    @Override
    public String getOrderWeChatThirdAppId(Long orderId, Integer plat) {
        OrderThirdAppBind orderThirdAppBind = getOrderWeChatBindInfoForOrderBy(orderId, plat);
        if (Objects.isNull(orderThirdAppBind)) {
            return null;
        }
        return orderThirdAppBind.getThirdAppId();
    }

    @Override
    public OrderThirdAppBind getOrderWeChatBindInfoForOrderBy(Long orderId, Integer plat) {
        OrderThirdAppBind orderThirdApp = orderThirdAppBindService.findByOrderIdAndPlat(orderId, plat);
        if (Objects.isNull(orderThirdApp) || StringUtils.isBlank(orderThirdApp.getThirdAppId())) {
            return null;
        }
        return orderThirdApp;
    }

    @Override
    public String getShortUrl(ShortUrlDTO shortUrlDTO) {
        ShortLinkDIO shortLinkDIO = new ShortLinkDIO();
        shortLinkDIO.setBussinessId(shortUrlDTO.getRuleId());
        shortLinkDIO.setName(shortUrlDTO.getOrderId() + ":sms:" + DateUtil.toString(DateUtil.getNow()));
        shortLinkDIO.setValidEndTime(Optional.ofNullable(shortUrlDTO.getValidEndTime()).orElse(DateUtil.addMonth(DateUtil.getNow(), 3)));
        shortLinkDIO.setLink(shortUrlDTO.getLink());
        shortLinkDIO.setMiniProgramsLink(shortUrlDTO.getMiniProgramsLink());
        shortLinkDIO.setType(shortUrlDTO.getShortLinkType());
        logger.info("订单号【{}】获取短链接getShortLink入参【{}】)", shortUrlDTO.getOrderId(), shortLinkDIO);
        ResponseDTO<ShortLinkDRO>  resp = shortLinkModifyRemoteService.getShortLink(shortLinkDIO);
        logger.info("订单号【{}】获取短链接getShortLink出参【{}】)", shortUrlDTO.getOrderId(), resp);
        if (!resp.isSuccess()) {
            return "";
        }
        return resp.getData().getQrCodeId();
    }

    @Override
    public String getFullShortUrl(ShortUrlDTO shortUrlDTO) {
        // 名字不能重复
        ShortLinkDIO shortLinkDIO = new ShortLinkDIO();
        shortLinkDIO.setBussinessId(shortUrlDTO.getRuleId());
        //shortLinkDIO.setName(shortUrlDTO.getOrderId() + ":sms:" + Optional.ofNullable(String.valueOf(shortUrlDTO.getRuleId())).orElse(DateUtil.toString(DateUtil.getNow())));
        shortLinkDIO.setName(shortUrlDTO.getOrderId() + ":sms:" + DateUtil.toString(DateUtil.getNow()));
        shortLinkDIO.setValidEndTime(Optional.ofNullable(shortUrlDTO.getValidEndTime()).orElse(DateUtil.addMonth(DateUtil.getNow(), 3)));
        shortLinkDIO.setLink(shortUrlDTO.getLink());
        shortLinkDIO.setMiniProgramsLink(shortUrlDTO.getMiniProgramsLink());
        shortLinkDIO.setType(shortUrlDTO.getShortLinkType());
        logger.info("订单号【{}】获取短链接getShortLink入参【{}】)", shortUrlDTO.getOrderId(), shortLinkDIO);
        ResponseDTO<ShortLinkDRO>  resp = shortLinkModifyRemoteService.getShortLink(shortLinkDIO);
        logger.info("订单号【{}】获取短链接getShortLink出参【{}】)", shortUrlDTO.getOrderId(), resp);
        if (!resp.isSuccess()) {
            return "";
        }
        return resp.getData().getUrl();
    }

    @Override
    public String getOrderUserRelationOpenId(Long orderId, Integer platWork, Long userId) {
        OrderThirdAppBind orderThirdAppBind = getOrderWeChatBindInfoForOrderBy(orderId, platWork);
        if (Objects.isNull(orderThirdAppBind)) {
            return null;
        }

        String thirdAppId = orderThirdAppBind.getThirdAppId();
        if (StringUtils.isBlank(thirdAppId)) {
            return null;
        }

        return getWeChatOpenIdByUserIdAndAppId(orderId, userId, thirdAppId);
    }

    @Override
    public OrderThirdAppBind getRemoteThirdAppBind(Long orderId, Long userId, Integer cityId, Integer plat) {
        try {
            logger.info("订单号={},获取微信公众号getAppByPlatAndUserId信息入参plat={}，userId={}，cityId={}", orderId, plat, userId, cityId);
            ResponseDTO<WxAppDRO> wxAppDROResponseDTO = appRemoteService.getAppByPlatAndUserId(plat, userId, cityId);
            logger.info("订单号={},获取微信公众号getAppByPlatAndUserId信息出参:【{}】", orderId, JSON.toJSON(wxAppDROResponseDTO));
            WxAppDRO wxAppDRO = wxAppDROResponseDTO.getData();
            if (Objects.isNull(wxAppDRO)) {
                return null;
            }

            logger.info("{}获取用户的openId入参getThirdByUserIdAndAppId  appId={}，userId={}", orderId, wxAppDRO.getThirdAppId(), userId);
            ResponseDTO<UserThirdBaseDRO> openIdRemote = userThirdListRemoteService.getThirdByUserIdAndAppId(userId, wxAppDRO.getThirdAppId());
            logger.info("{}获取用户的openId出参getThirdByUserIdAndAppId【{}】", orderId, openIdRemote);
            UserThirdBaseDRO userThirdBaseDRO = openIdRemote.getData();
            if (Objects.isNull(userThirdBaseDRO)) {
                return null;
            }
            OrderThirdAppBind orderThirdAppBind = new OrderThirdAppBind();
            orderThirdAppBind.setThirdAppId(wxAppDRO.getThirdAppId());
            orderThirdAppBind.setThirdAppName(wxAppDRO.getName());
            orderThirdAppBind.setAppShopId(userThirdBaseDRO.getShopId());
            return orderThirdAppBind;
        } catch (Exception ex) {
            logger.error(String.format("订单号%s，获取微信公众号getAppByPlatAndUserId接口异常了:%s", orderId, ex.getMessage()), ex);
            return null;
        }
    }

    @Override
    public String getWeChatOpenIdByUserIdAndAppId(Long orderId, Long userId, String appId) {
        if (StringUtils.isBlank(appId)) {
            return null;
        }
        logger.info("{}获取用户的openId入参getThirdByUserIdAndAppId  appId={}，userId={}", orderId, appId, userId);
        ResponseDTO<UserThirdBaseDRO> openIdRemote = userThirdListRemoteService.getThirdByUserIdAndAppId(userId, appId);
        logger.info("{}获取用户的openId出参getThirdByUserIdAndAppId【{}】", orderId, openIdRemote);
        if (!openIdRemote.isSuccess() || Objects.isNull(openIdRemote.getData())) {
            logger.info("#oms#getThirdByUserIdAndAppId 用户[{}]openId不存在", userId);
            return null;
        }
        return openIdRemote.getData().getOpenId();
    }

    /**
     * 获取用户openId，且判断当前用户是否关注公众号，未关注返回空
     * subscribe 这个字段，1，表示关注，0表示没关注
     *
     * @param appId
     * @return
     */
    @Override
    public String getWeChatOpenIdAndCheckUserSubscribe(Long orderId, Long userId, String appId) {
        String openId = getWeChatOpenIdByUserIdAndAppId(orderId, userId, appId);
        if (StringUtils.isBlank(openId)) {
            return null;
        }
        try {
            logger.info("订单号={},判断当前用户是否关注公众号入参openId={},appId={}", orderId, openId, appId);
            ResponseDTO<WeixinUserInfoDRO> resp = privateQrCodeListRemoteService.getWeChatUserInfo(openId, appId);
            logger.info("订单号={},判断当前用户是否关注公众号getWeChatUserInfo出参【{}】", orderId, resp);
            if (resp.isSuccess() && Objects.nonNull(resp.getData())) {
                Integer subscribe = resp.getData().getSubscribe();
                if (Objects.equals(subscribe, 1)) {
                    return openId;
                }
            }
        } catch (Exception ex) {
            logger.error(String.format("订单号%s，判断当前用户是否关注公众号接口getWeChatUserInfo异常了:%s", orderId, ex.getMessage()), ex);
            return null;
        }
        return null;
    }

    @Override
    public UserThirdBaseDRO getWeChatUserInfoByTelephone(Long orderId, String telephone, String appId) {
        logger.info("#OMS#订单号={},根据电话号码获取订单用户信息listByMobile入参telephone={}，appId={}", orderId, telephone, appId);
        ResponseDTO<List<UserThirdBaseDRO>> userThirdResp = userThirdListRemoteService.listByMobile(telephone);
        logger.info("#OMS#订单号={},根据电话号码获取订单用户信息listByMobile出参{}", orderId, JSON.toJSON(userThirdResp));

        List<UserThirdBaseDRO> userThirds = userThirdResp.getData();
        if (!userThirdResp.isSuccess() || Objects.isNull(userThirds)) {
            logger.info("#oms#订单号{}listByMobile 根据手机{}号为找人任何信息", orderId, telephone);
            return null;
        }
        userThirds.stream().map(student -> student.getAppId() != null);
        // 根据appId 转换map集合
        Map<String, UserThirdBaseDRO> userMapDRO = userThirds.stream().collect(Collectors.toMap(UserThirdBaseDRO::getAppId, Function.identity(), (item1, item2) -> item2));
        UserThirdBaseDRO userThird = userMapDRO.get(appId);
        if (Objects.isNull(userThird)) {
            return null;
        }
        return userThird;
    }

    @Override
    public String getUserMobileByUserId(Long orderId, Long userId) {
        if (NumberUtil.isNullOrZero(userId)) {
            return null;
        }
        ResponseDTO<UserDetailDRO> userResponseDTO = userListRemoteService.getUserDetailById(userId, false);
        logger.info("订单号{}send根据用户Id获取用户详情信息#getUserDetailById入参userId={},isSensitive=false;出参={}", orderId, userId, userResponseDTO);
        UserDetailDRO userDetailDRO = userResponseDTO.getData();
        if (Objects.isNull(userDetailDRO)) {
            return null;
        }

        return userDetailDRO.getMobile();
    }

    @Override
    public boolean isTempUser(Long orderId, Long userId) {
        // 判断是否为临时用户
        boolean isTempUser = true;
        if (NumberUtil.isNullOrZero(userId)) {
            return true;
        }
        ResponseDTO<UserDetailDRO> userDetailDROResponseDTO = userListRemoteService.getUserById(userId, false);
        logger.info("#oms#订单号{}获取用户信息#getUserById入参userId={},isSensitive=false;出参={}", orderId, userId, userDetailDROResponseDTO);
        UserDetailDRO userDetailDRO = userDetailDROResponseDTO.getData();
        if (!userDetailDROResponseDTO.isSuccess() || Objects.isNull(userDetailDRO)) {
            return true;
        }
        // 正式用户
        if (Objects.equals(userDetailDRO.getTempFlag(), GlobalConsts.NO)) {
            isTempUser = false;
        }
        logger.info("#oms#订单号{}用户Id={}是否临时用户={}", orderId, userId, isTempUser);
        return isTempUser;
    }

    /**
     * 判断是否非直营工程师
     *
     * @param masterId
     * @return
     */
    @Override
    public boolean isNotAgent(Integer masterId) {
        // 是否非直营工程师
        boolean isNotAgent = false;
        // 查询工程师信息
        // todo fubiao
        logger.info("isNotAgent#getEngineerDetailById 入参 [{}]",masterId);
        ResponseDTO<ForeignEngineerDetailInfoDRO> cacheEngineerByEngineerId = engineerListRemoteService.getEngineerDetailById(masterId);
        logger.info("isNotAgent#getEngineerDetailById 出参 [{}]",JSON.toJSONString(cacheEngineerByEngineerId));
        ForeignEngineerDetailInfoDRO baseEngineerDRO = cacheEngineerByEngineerId.getData();
        if (cacheEngineerByEngineerId.isSuccess() && baseEngineerDRO != null) {
            // 代理商标志：1直营，2加盟，3承包
            // 非直营工程师 微信不推送消息&&短信取消费用：XX元
            isNotAgent = Objects.equals(1, baseEngineerDRO.getCooperationType());
        }
        return isNotAgent;
    }

    @Override
    public String checkWarrantyAndGetWarrantyCode(Long orderId) {
        // 查看主库获取保修卡信息
        WarrantyVO warrantyVO = orderWarrantyBService.findWarrantyVOByOrderId(orderId);
        if (Objects.isNull(warrantyVO)) {
            logger.error("#oms#processWarranty#{} 订单电子保修卡不存在", orderId);
            return null;
        }
        // type：1 收据，2保修卡，新业务模式已取消收据
        if (Objects.equals(warrantyVO.getType(), 1)) {
            logger.info("工单号{}send，该订单属于收据类型，新业务没有收据，不发送保修收据模板消息", orderId);
            return null;
        }
        return warrantyVO.getCode();
    }


    @Override
    public boolean deleteOrderBaiduSceneIds(Long orderId) {
        // 删除redis 公众号解绑
        String redisKey = String.format(RedisKeyConsts.BAIDU_SCENEIDS_REDIS_KEY, String.valueOf(orderId));
        boolean isExists = redisManager.exists(redisKey);
        if (isExists) {
            boolean isUnBind = redisManager.del(redisKey);
            logger.info("订单号【{}】删除百度表单消息【{}】", orderId, isUnBind);
        }
        return true;
    }

    /**
     * 根据微信appId 获取渠道信息
     *
     * @param thirdAppId
     * @return
     */
    private Integer getWeChatChannelIdByThirdAppId(Long orderId, String thirdAppId) {
        if (StringUtils.isBlank(thirdAppId)) {
            return 0;
        }
        ResponseDTO<Integer> resp = appRemoteService.getChannelIdByThirdAppKey(thirdAppId);
        logger.info("#oms#订单号{}根据微信appId 获取渠道信息getChannelIdByThirdAppKey入参thirdAppKey={},出参={}", orderId, thirdAppId, resp);
        Integer wechatChannelId = resp.getData();
        if (NumberUtil.isNullOrZero(wechatChannelId)) {
            return null;
        }
        return wechatChannelId;
    }

}